/*
MIT License 

Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов, 

https://bmstu.codes/lsx/simodo/loom
*/

#ifndef simodo_module_CodeSupplier
#define simodo_module_CodeSupplier

/*! \file CodeSupplier.h
    \brief Генератор кода для интерпретации.
    
*/

#include "simodo/module/CodeSupplier_interface.h"
#include "simodo/inout/reporter/Reporter_abstract.h"
#include "simodo/inout/token/InputStreamSupplier_interface.h"
#include "simodo/loom/Loom.h"
#include "simodo/parser/Grammar.h"
#include "simodo/parser/SyntaxDataCollector_interface.h"

#include <vector>
#include <unordered_map>

namespace simodo::module
{
    /**
     * @brief Интерфейс генератора кода для интерпретации.
     * 
     */
    class CodeSupplier: public CodeSupplier_interface
    {
        inout::Reporter_abstract &                  _m;                 ///< Обработчик сообщений
        std::vector<std::string>                    _grammar_places;
        inout::InputStreamSupplier_interface &      _stream_supplier;   ///< Система предоставления контента
        parser::SyntaxDataCollector_interface &     _syntax_data_collector;

        std::unordered_map<std::string,const parser::Grammar> 
                                                    _grammar_tables;
        loom::Loom                                  _loom;          ///< Система исполнения генерации кода
        std::unordered_map<std::string,ast::Node>   _codes;

        std::string                                 _last_error;

    public:
        CodeSupplier() = delete;
        CodeSupplier(inout::Reporter_abstract & m, 
                     std::vector<std::string> grammar_places,
                     inout::InputStreamSupplier_interface & stream_supplier,
                     parser::SyntaxDataCollector_interface & syntax_data_collector);

        virtual const ast::Node *   getCode(const std::string & module_name,
                                            const inout::uri_set_t & files) override;

        virtual const std::string & last_error() const override { return _last_error; }

    protected:
        std::string                 findGrammarFile(const std::string & grammar_name) const;
        bool                        parse(const inout::uri_set_t & files,
                                          inout::uri_index_t uri_index, 
                                          inout::InputStream_interface & stream, 
                                          const std::string & grammar_file, 
                                          ast::Node & code);
        const parser::Grammar &     getGrammarTable(const std::string & grammar_file);
        bool                        buildGrammarTable(const std::string & grammar_name,
                                                      const inout::uri_set_t & fuze_files, 
                                                      const ast::Node & fuze_code, 
                                                      parser::TableBuildMethod method,
                                                      parser::Grammar & grammar_table);
    };

}

#endif // simodo_module_CodeSupplier
